#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<errno.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#define LISTEN_PORT	9999
#define BACKLOG		13

void print_usage(char *progname)
{
	printf("%s usage: \n",progname);
	printf("-p(--port): specify server listen port.\n");
	printf("-h(--help): print this help information.\n");
}
int main(int argc,char **argv)
{
	int 			listen_fd=-1;
	int 			cli_fd=-1;
	int 			rv=-1;
	struct sockaddr_in	serv_addr;
	struct sockaddr_in	cli_addr;
	socklen_t		cliaddr_len;
	char			buf[1024];
	
	struct	opts[]={
		{"port",required_argument,NULL,'p'},
		{"help",no_arguments,NULL,'h'},
		{NULL,0,NULL,0}
	};

	while(ch=getopt_long(argc,argv,"p:h",opts,NULL))!=-1)
	{
		switch(ch)
		{
			case 'p':
				port=atoi(optarg);
				break;
			case 'h':
				printf_usage(argv[0]);
				return 0;
		}
	}
	if(!port)
	{
		print_usage(argv[0];
			return 0;
	}

	//服务器端 首先创建socket  ipv4 tcp 0
	listen_fd=socket(AF_INET,SOCK_STREAM,0);
	if(listen_fd<0)
	{
		printf("Create a socket failure: %s!\n",strerror(errno));
		return -1;
	}
	printf("Create a socket[%d] successfully!\n",listen_fd);
	
	//保证
	setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeod(on));
	
	
	//第二步，重置服务器端的数据 为什么这里求大小用的是指针呢？
	memset(&serv_addr,0,sizeof(serv_addr));
	serv_addr.sin_family=AF_INET;
	serv_addr.sin_port=htons(LISTEN_PORT);
	serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);

	//第三步步 bind
	if((bind(listen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0))
	{
		printf("Create a socket[%d] failure: %s!\n",listen_fd,strerror(errno));
		return -2;
	}
	printf("Socket[%d] bind on port[%d] for all IP ok!\n",listen_fd,LISTEN_PORT);

	//第四步 服务器监听
	listen(listen_fd,BACKLOG);
	printf("Start to listen on port [%d]\n",port);

	while(1)
	{

		printf("Waiting for client to connect...\n");
		cli_fd=accept(listen_fd,(struct sockaddr*)&cli_addr,&cliaddr_len);
		if(cli_fd<0)
		{
			printf("Connect to client failure!\n");
			return -3;
		}
		printf("Connect to client[%s:%d] on socket[%d] successfully!\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port),listen_fd);
		
		pid=fork();
		//当前是子程序
		if(0==pid)
		{
			char		buf[1024];
			int		i;

			printf("Child process satrt to communicate with socket\n");
			close(listen_fd);

			while(1)
			{
				//读取文件
				memset(buf,0,sizeof(buf));
				rv=read(cli_fd,buf,sizeof(buf));
			if(rv<0)
			{
				printf("Read data from client in socket[%d] failure!\n",cli_fd);
				close(cli_fd);
			}
			else if(0==rv)
			{
				printf("Client get disconnected!\n");
				close)cli_fd);
			}
			printf("Read data %d bytes : %s from sock[%d]!\n",rv,buf,cli_fd);

			if(write(cli_fd,buf,rv)<0)
			{
				printf("Write back to client socket[%d] failure:%s!\n",cli_fd,strerror(errno));
				close(cli_fd);
			}
			printf("Write to client socket[%d] successfully!\n",cli_fd);
			sleep(1);
			close(cli_fd);
			exit(0);
			}
		}
		else if(pid>0)
		{
			//父进程
			close(cli_fd);
			continue;
		}
		else{
			printf("Fork() create child process failure: %s\nq",strerror(errno));
			close(cli_fd);
			continue;
		}
	}

	close(listen_fd);

}
